/** 
Copyright (c) 2010, Sheikh Abdul Wahid Ahmed
Details @ http://extremecodeworld.codeplex.com/license
**/

using System;
using System.Security.Cryptography;
using System.IO;
using System.Text;
using Microsoft.Win32;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace EXtremecode.Utils
{
	/// <summary>
	/// Summary description for DataEncryptor.
	/// </summary>
	public class DataEncryptor
	{
		private static DataEncryptor singleton;
		private ICryptoTransform encryptor;
		private ICryptoTransform decryptor;
		DataEncryptor(string secretKey)
		{
			PasswordDeriveBytes pdb = new PasswordDeriveBytes(secretKey, 
				new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
							   0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); 

			
			// Create a new instance of the RC2CryptoServiceProvider class
			// and automatically generate a Key and IV.
			byte[] key= pdb.GetBytes(32); 
			byte[] iv = pdb.GetBytes(16); 
			//TripleDESCryptoServiceProvider  rc2CSP = new TripleDESCryptoServiceProvider();
            Rijndael rc2CSP = Rijndael.Create();

			// Get an encryptor.
			encryptor = rc2CSP.CreateEncryptor(key, iv);
			
			//Get a decryptor that uses the same key and IV as the encryptor.
			decryptor = rc2CSP.CreateDecryptor(key, iv);


			
		}
		public static DataEncryptor Instance
		{
			get
			{
				return CreateInstance("SheikhAbdulWahid");
			}
		}

		public static DataEncryptor CreateInstance(string secretKey)
		{
			if(singleton==null)
			{
				singleton=new DataEncryptor(secretKey);
			}
			return singleton;
		}

		public string GetEncryptedString(string plainText)
		{
			
			byte[] toEncrypt = Encoding.Unicode.GetBytes(plainText);
			MemoryStream memStream = new MemoryStream();
			CryptoStream cryptStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write);
		   
			cryptStream.Write(toEncrypt, 0, toEncrypt.Length);
			cryptStream.FlushFinalBlock();

			// Get the encrypted array of bytes.
			byte[] encrypted = memStream.ToArray();
			return Convert.ToBase64String(encrypted);
		}

		public string GetDecryptedString(string encryptedData)
		{
			
			byte[] toDecrypt = Convert.FromBase64String(encryptedData);

			MemoryStream memStream = new MemoryStream();
			CryptoStream cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Write);
		    
			cryptoStream.Write(toDecrypt,0,toDecrypt.Length);
			cryptoStream.Close();
			
			return Encoding.Unicode.GetString(memStream.ToArray()); 
		}

		
		
		private static object isGeneratingAllowed = null;
		public static bool IsGeneratingAllowed
		{
			get
			{
				return true;
				if(IsAllowed)
				{
					return (bool)isGeneratingAllowed; 
				}
				else
				{
					return false;
				}
			}
		}
		
		private static object isAllowed = null;
		public static bool IsAllowed
		{
			get
			{
				return true;
				if(isAllowed != null)
				{
					return (bool)isAllowed;
				}
				RegistryKey regKey= null;
				RegistryKey registeredRegKey = null;
				try
				{
					regKey = Registry.LocalMachine;
					
					//check if product registered
					string registeredKeyAddress = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\File Manager\Downloads"; 
					registeredRegKey = regKey.OpenSubKey(registeredKeyAddress);
					if(registeredRegKey == null || 
						registeredRegKey.GetValue("IsRegistered") == null ||
						registeredRegKey.GetValue("IsRegistered").ToString() != "true") 
					{
						//product is not registered	
						isAllowed= false;
						return (bool)isAllowed;
					}
				
					//check validity.
					DateTime registeringDate = DateTime.ParseExact(registeredRegKey.GetValue("Date").ToString(),"dd/MM/yyyy",new System.Globalization.DateTimeFormatInfo());
					string strDate = DateTime.Today.ToString("dd/MM/yyyy");
					string originalSerialNum = registeredRegKey.GetValue("SerialNumber").ToString();
					DateTime validTillDate = DateTime.ParseExact(DataEncryptor.Instance.GetDecryptedString(originalSerialNum),"dd/MM/yyyy",new System.Globalization.DateTimeFormatInfo());
				
					if(validTillDate > DateTime.Today)
					{
						isAllowed= true;
						int generatorDays = int.Parse(registeredRegKey.GetValue("GDays").ToString());
						if(registeringDate > DateTime.Today)
						{
							//some body has changed system date.
							isGeneratingAllowed=false;
						}
						else if(DateTime.Today.Subtract(registeringDate).TotalDays > generatorDays )
						{
							isGeneratingAllowed=false;
						}
						else
						{
							//ok
							isGeneratingAllowed=true;
						}
					}
					else
					{
						isAllowed= false;
					}
					return (bool)isAllowed;
				}
				catch
				{
					return false;
				}
				finally
				{
					if(regKey != null) 
					{
						regKey.Close();
					}

					if(registeredRegKey != null) 
					{
						registeredRegKey.Close();
					}

					
				}
			}
		}
		
	
	}
}
